import cv2
import requests
import threading
import socket
import select
import time

# 服务器URL
lunch_code = '1631'
id = str(0)
video_server_url = f'http://yangyangyou.com/get_video/{lunch_code}{id}'
data_server_url = f'http://yangyangyou.com/get_data_rst/{lunch_code}{id}'
comd_server_url = f'http://yangyangyou.com/upload_comd/{lunch_code}{id}'


def tcp_server_init():
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp_server_socket.bind(('127.0.0.1', 8888))
    tcp_server_socket.listen(1)
    return tcp_server_socket

def video_thread_function():
    video_response = cv2.VideoCapture(video_server_url)
    while True:
        ret, frame = video_response.read()
        if not ret:
            print("Failed to receive video frame")
            break
        cv2.imshow('Video', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cv2.destroyAllWindows()

def combined_listener_sender():
    tcp_server = tcp_server_init()
    tcp_server.settimeout(1)  # 设置超时以允许中断

    while True:
        print("Waiting for TCP connection...")
        try:
            conn, addr = tcp_server.accept()
            conn.setblocking(False)  # 非阻塞模式
            print(f"Connected to {addr}")

            msg_buffer = bytearray()
            buffer_lock = threading.Lock()
            running = True

            def data_fetcher():
                while running:
                    try:
                        resp = requests.get(data_server_url)
                        if resp.status_code == 200:
                            data = resp.json()
                            hex_str = ''.join([item[1] for item in data])
                            with buffer_lock:
                                msg_buffer.extend(bytes.fromhex(hex_str))
                    except Exception as e:
                        print(f"Data fetch error: {e}")
                    time.sleep(0.01)

            fetcher_thread = threading.Thread(target=data_fetcher)
            fetcher_thread.start()

            try:
                while True:
                    # 使用select管理I/O事件
                    rlist, wlist, _ = select.select([conn], [conn], [], 0.1)

                    # 处理接收命令
                    if conn in rlist:
                        try:
                            data = conn.recv(4096)
                            print(f"Sending {data}")
                            if data:
                                hex_cmd = data.hex()
                                # 异步发送命令避免阻塞
                                threading.Thread(target=requests.post,
                                                 args=(comd_server_url,),
                                                 kwargs={'data': {'comd_data': hex_cmd}}).start()
                            else:
                                break  # 连接关闭
                        except BlockingIOError:
                            pass

                    # 处理发送数据
                    with buffer_lock:
                        if msg_buffer and conn in wlist:
                            try:
                                print(f"Receiving {msg_buffer}")
                                sent = conn.send(msg_buffer)
                                msg_buffer = msg_buffer[sent:]
                            except (BlockingIOError, ConnectionResetError):
                                pass

            except Exception as e:
                print(f"Connection error: {e}")
            finally:
                running = False
                fetcher_thread.join()
                conn.close()
                print("Connection closed")

        except socket.timeout:
            continue  # 重新等待新连接
        except Exception as e:
            print(f"Accept error: {e}")

if __name__ == '__main__':
    video_thread = threading.Thread(target=video_thread_function)
    video_thread.start()
    combined_listener_sender()